import { Service } from "egg";
import { Op } from "sequelize";

export default class DocumentService extends Service {
  /**
   * 创建文档并返回基础信息
   */
  public async createDocument(userId: string, title: string) {
    const { models } = this.app as any;

    // 1. 创建文档基础信息
    const doc = await models.Document.create({
      title,
      owner_id: userId,
      status: 1,
      content: JSON.stringify([{ type: "paragraph", content: [{ type: "text", text: "开始编写你的文档..." }] }])
    });

    // 2. 同时创建对应的 Yjs 文档记录
    const Y = require("yjs");
    const ydoc = new Y.Doc();

    // 创建初始的空文档状态
    const initialState = Y.encodeStateAsUpdate(ydoc);
    const stateBuffer = Buffer.from(initialState);

    await models.YjsDocument.create({
      document_id: doc.id,
      room_name: doc.id, // 使用文档ID作为房间名
      yjs_state: stateBuffer,
      last_updated: new Date(),
      version: 1
    });

    console.log(`✅ 文档 ${doc.id} 及其 Yjs 协同记录创建成功`);

    return {
      id: doc.id,
      title: doc.title,
      ownerId: doc.owner_id,
      createdAt: doc.created_at,
      updatedAt: doc.updated_at
    };
  }
  /**
   * 获取当前用户可见的文档列表（拥有者 + 协作）
   */
  public async listUserDocuments(userId: string) {
    const { models } = this.app as any;

    // 拥有的文档
    const owned = await models.Document.findAll({
      where: { owner_id: userId, status: 1 },
      order: [["updated_at", "DESC"]]
    });

    // 参与协作的文档（无status字段，存在记录即视为已授权）
    const collaborated = await models.Document.findAll({
      where: { status: 1 },
      include: [
        {
          model: models.DocumentCollaboration,
          as: "collaborations",
          where: { user_id: userId },
          required: true
        }
      ],
      order: [["updated_at", "DESC"]]
    });

    const toDto = (doc: any, isOwner: boolean) => ({
      id: doc.id,
      title: doc.title,
      ownerId: doc.owner_id,
      createdAt: doc.created_at,
      updatedAt: doc.updated_at,
      isOwner
    });

    return [...owned.map((d: any) => toDto(d, true)), ...collaborated.map((d: any) => toDto(d, false))];
  }

  /**
   * 获取用户可访问的文档详情
   */
  public async getDocumentDetail(documentId: string, userId: string) {
    const { models } = this.app as any;

    const doc = await models.Document.findOne({ where: { id: documentId, status: 1 } });
    if (!doc) return null;

    const canAccess = await this.canRead(documentId, userId);
    if (!canAccess) return null;

    return {
      id: doc.id,
      title: doc.title,
      content: doc.content ? JSON.parse(doc.content) : null,
      ownerId: doc.owner_id,
      createdAt: doc.created_at,
      updatedAt: doc.updated_at
    };
  }

  /**
   * 保存文档内容（BlockNote JSON 快照）
   */
  public async saveDocumentContent(documentId: string, userId: string, content: any) {
    const { models } = this.app as any;

    const canWrite = await this.canWrite(documentId, userId);
    if (!canWrite) return { ok: false, code: "NO_PERMISSION" } as const;

    const doc = await models.Document.findOne({ where: { id: documentId, status: 1 } });
    if (!doc) return { ok: false, code: "NOT_FOUND" } as const;

    // 处理 content：如果是字符串则先解析，确保是有效的JSON对象
    let processedContent = content;
    if (typeof content === 'string') {
      try {
        processedContent = JSON.parse(content);
      } catch (e) {
        // 如果解析失败，说明不是有效的JSON字符串，直接使用原值
        processedContent = content;
      }
    }

    await doc.update({
      content: JSON.stringify(processedContent),
      last_sync_at: new Date()
    });

    return { ok: true } as const;
  }

  /**
   * 邀请协作（默认同意）：校验邀请人是否有 admin 或 owner 权限
   */
  public async inviteCollaborator(
    documentId: string,
    inviterId: string,
    userId: string,
    permission: "read" | "write" | "admin"
  ) {
    const { models } = this.app as any;

    // 1) 校验文档存在
    const doc = await models.Document.findOne({ where: { id: documentId, status: 1 } });
    if (!doc) return { ok: false, code: "NOT_FOUND", message: "文档不存在" } as const;

    // 2) 只有文档所有者或已有 admin 权限的协作者可以邀请
    const isOwner = String(doc.owner_id) === String(inviterId);
    let isAdmin = false;
    if (!isOwner) {
      const adminCollab = await models.DocumentCollaboration.findOne({
        where: { document_id: documentId, user_id: inviterId, permission: "admin" }
      });
      isAdmin = !!adminCollab;
    }
    if (!isOwner && !isAdmin) {
      return { ok: false, code: "NO_PERMISSION", message: "没有邀请权限" } as const;
    }

    // 3) upsert 协作关系（默认同意）
    await models.DocumentCollaboration.upsert({
      document_id: documentId,
      user_id: userId,
      permission,
      invited_by: inviterId,
      invited_at: new Date(),
      responded_at: new Date()
    });

    // upsert 在不同 dialect/版本返回不一致，这里统一再查一次
    const saved = await models.DocumentCollaboration.findOne({
      where: { document_id: documentId, user_id: userId }
    });

    return { ok: true, data: { id: saved?.id, documentId, userId, permission } } as const;
  }

  private async canRead(documentId: string, userId: string): Promise<boolean> {
    const { models } = this.app as any;
    const doc = await models.Document.findOne({ where: { id: documentId, status: 1 } });
    if (!doc) return false;
    if (String(doc.owner_id) === String(userId)) return true;

    const collab = await models.DocumentCollaboration.findOne({
      where: { document_id: documentId, user_id: userId }
    });
    return !!collab;
  }

  private async canWrite(documentId: string, userId: string): Promise<boolean> {
    const { models } = this.app as any;
    const doc = await models.Document.findOne({ where: { id: documentId, status: 1 } });
    if (!doc) return false;
    if (String(doc.owner_id) === String(userId)) return true;

    const collab = await models.DocumentCollaboration.findOne({
      where: {
        document_id: documentId,
        user_id: userId,
        permission: { [Op.in]: ["write", "admin"] }
      }
    });
    return !!collab;
  }
}
